May 94 Tips
Volume Number: 10
Issue Number: 5
Column Tag: Tips & Tidbits
Related Info: Font Manager Window Mgr
Tips & Tidbits
By Scott T Boyd, Editor
Note: Source code files accompanying article are located on MacTech CD-ROM or
source code disks.
Tip Of The Month
Counting items in a directory
Here’s a piece of code which counts the number of items in a directory. It’s
particularly useful if you are going to do something to every file in a directory (and its
subdirectories) and want to show a progress bar. It counts both invisible and visible
items, so if you don’t want invisibles counted, you’ll need to modify it. The
CountGlobals structure is used to minimize the amount of stack space used when
recursively calling GetLevelCount and to hold global information that might be needed
at any time.
- Jim Luther, Cupertino, CA
/* 1 */
struct CountGlobals
{
OSErr result; // temp holder of results - saves 2
bytes of stack at each level
Str63 itemName; // the name of the current item
CInfoPBRec myCPB; // the parameter block used for
PBGetCatInfo calls
unsigned long files; // the number of files in the directory
structure
unsigned long directories; // the number of directories in the
directory structure
};
typedef struct CountGlobals CountGlobals;
typedef CountGlobals *CountGlobalsPtr;
// static prototypes
static void GetLevelCount( long currentDirID,
CountGlobalsPtr theGlobals);
void CountDirectoryItems(short srcVRefNum, long srcDirID,
unsigned long * files, unsigned long *directories);
static void GetLevelCount( long currentDirID,
CountGlobalsPtr theGlobals)
{
short index = 1;
do {
theGlobals->myCPB.dirInfo.ioFDirIndex = index;
// we need to do this every time through; GetCatInfo returns
ioFlNum in this field
theGlobals->myCPB.dirInfo.ioDrDirID = currentDirID;
theGlobals->result =
PBGetCatInfoSync((CInfoPBPtr)&theGlobals->myCPB);
if (theGlobals->result == noErr)
{
if ((theGlobals->myCPB.dirInfo.ioFlAttrib & ioDirMask) != 0)
{
// we have a directory
++(theGlobals->directories);
GetLevelCount( theGlobals->myCPB.dirInfo.ioDrDirID,
theGlobals); // recurse
theGlobals->result = noErr; // clear error return on way back
}
else
{
// we have a file
++(theGlobals-> files);
}
}
++index;
} while (theGlobals->result == noErr);
}
void CountDirectoryItems(short srcVRefNum,
long srcDirID,
unsigned long * files,
unsigned long *directories)
{
CountGlobals theGlobals;
theGlobals.myCPB.dirInfo.ioNamePtr = theGlobals.itemName;
theGlobals.myCPB.dirInfo.ioVRefNum = srcVRefNum;
theGlobals.files = 0;
theGlobals.directories = 0;
GetLevelCount(srcDirID, &theGlobals);
*files = theGlobals. files;
*directories = theGlobals.directories;
}
Spread the word about things you know that others could benefit from knowing!
Send
us your tips and tidbits, e specially programming-related tips. We’re also
looking for user tips particularly useful to programmers .
MacTech Magazine will pay $25 for every tip used, and $50 for the Tip of the
Month. You can take your award in orders or subscriptions if you prefer.
To submit a tip, send it in by e-mail. (Please make sure your code compiles).
See page two for our addresses.
Popup Menus Pop Up Again
In the February issue, Laurent Haas suggested a method of forcing pop-up menus
to appear in a certain font and size. His method involved forcing the system to use a
new system font. I used to use this method as well, since it was the method suggested in
an Apple DTS Q&A stack. Unfortunately, it has two drawbacks:
(1) It is very slow because the system has to rebuild the cached font info every time
the font manager sees that LastSPExtra (the global variable at 0x0B4C) is -1.
(That is why the -1 is being stuffed in there in the first place - otherwise the
other changes are ignored because of the caching).
(2) It doesn’t work - no kidding... if it works consistently on a particular machine,
you are very lucky. Much of the time it simply does not have the desired effect -
usually the font will change, but the size won't.
The method I use now is to patch _TextFont and _TextSize immediately before
calling PopupMenuSelect and then unpatch them immediately afterwards (to minimize
interference with anything else that uses these traps). My patches call the original
routine but with a substituted argument for the font number or size. This works
consistently and has no speed penalty to speak of. After unpatching, I also need to
restore the font and size of the window manager port, since the menu defproc has
explicitly set them by calling TextFont(0) and TextSize(0). Because of the patches,
the WMgrPort now has a font and size different from the system font and size. I set the
current port to the WMgrPort and do a TextFont and a TextSize to set them back to 0.
On a colour Mac, this must also be done for the Colour Window manager port as well.
This method doesn’t use any low memory globals, so is less likely to break. It
does, however, require tweaking the window manager port(s), which could possibly
break but I doubt it.
- Rowan Daniell, Software Engineer, Cowie Associates Ltd
Moving Targets In Mpw
With the advent of the Universal C interfaces it is a pain switching back and forth
between the CIncludes and PPCCIncludes folders. Adding the following three lines to
your UserStartUp- script will make life easier:
/* 2 */
AddMenu Tools 'Use Universal CIncludes' ∂
'SET CIncludes "{MPW}Interfaces:PPCCIncludes:"'
AddMenu Tools 'Use Standard CIncludes' ∂
'SET CIncludes "{MPW}Interfaces:CIncludes:"'
AddMenu Tools (- ''
Any menu can be specified, but I chose to add these commands to the top of my
Tools menu (which is also why I added a dividing line beneath the two items). Selecting
an item causes the shell variable {CIncludes} to be set to the appropriate path. This can
make life much easier when jumping between older projects and new, PowerPC-savvy
projects.
- Bryan Pietrzak, Softdisk Publishing